package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.IdAndNumDTO;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.domain.query.PageQuery;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.*;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.PlanStatus;
import com.tianji.learning.mapper.LearningLessonMapper;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.domain.vo.LearningLessonVO;
import com.tianji.learning.domain.vo.LearningPlanPageVO;
import com.tianji.learning.domain.vo.LearningPlanVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 学生课程表 服务实现类
 * </p>
 *
 * @author 柏彪
 * @since 2025-02-28
 */
@SuppressWarnings("ALL")
@Service
@RequiredArgsConstructor
@Slf4j
public class LearningLessonServiceImpl extends ServiceImpl<LearningLessonMapper, LearningLesson> implements ILearningLessonService {
//
//    private final CourseClient courseClient;
//
//    private final CatalogueClient catalogueClient;
//
//    private final LearningRecordMapper recordMapper;
//
//    @Override
//    public void addUserLessons(Long userId, List<Long> courseIds) {
//        // 1、查询课程有效期
//        List<CourseSimpleInfoDTO> cInfoList = courseClient.getSimpleInfoList(courseIds);
//        if (CollUtils.isEmpty(cInfoList)){
//            // 课程不存在。无法添加
//            log.error("课程信息不存在，无法添加到课表");
//            return;
//        }
//        // 2、循环遍历，处理LearningLesson数据
//        List<LearningLesson> list = new ArrayList<>(cInfoList.size());
//        for (CourseSimpleInfoDTO cInfo : cInfoList){
//            LearningLesson lesson = new LearningLesson();
//            // 2.1 获取过期时间
//            Integer validDuration = cInfo.getValidDuration();
//            if (validDuration != null && validDuration > 0){
//                LocalDateTime now  = LocalDateTime.now();
//                lesson.setCreateTime(now);
//                lesson.setExpireTime(now.plusMonths(validDuration));
//            }
//            // 2.2、填充userId和courseId
//            lesson.setUserId(userId);
//            lesson.setCourseId(cInfo.getId());
//            list.add(lesson);
//        }
//        // 3、批量新增
//        saveBatch(list);
//    }
//
//    @Override
//    public PageDTO<LearningLessonVO> queryMyLessons(PageQuery query) {
//        // 1.获取当前登录用户
//        Long userId = UserContext.getUser();
//        // 2.分页查询
//        // select * from learning_lesson where user_id = #{userId} order by latest_learn_time limit 0, 5
//        Page<LearningLesson> page = lambdaQuery()
//                .eq(LearningLesson::getUserId, userId) // where user_id = #{userId}
//                .page(query.toMpPage("latest_learn_time", false));
//        List<LearningLesson> records = page.getRecords();
//        if (CollUtils.isEmpty(records)) {
//            return PageDTO.empty(page);
//        }
//        // 3.查询课程信息
//        Map<Long, CourseSimpleInfoDTO> cMap = queryCourseSimpleInfoList(records);
//
//        // 4.封装VO返回
//        List<LearningLessonVO> list = new ArrayList<>(records.size());
//        // 4.1.循环遍历，把LearningLesson转为VO
//        for (LearningLesson r : records) {
//            // 4.2.拷贝基础属性到vo
//            LearningLessonVO vo = BeanUtils.copyBean(r, LearningLessonVO.class);
//            // 4.3.获取课程信息，填充到vo
//            CourseSimpleInfoDTO cInfo = cMap.get(r.getCourseId());
//            vo.setCourseName(cInfo.getName());
//            vo.setCourseCoverUrl(cInfo.getCoverUrl());
//            vo.setSections(cInfo.getSectionNum());
//            list.add(vo);
//        }
//        return PageDTO.of(page, list);
//    }
//
//    @Override
//    public LearningLessonVO queryMyCurrentLesson() {
//        //  1.获取当前登录用户
//        Long userId = UserContext.getUser();
//        // 2、查询正在学习的课程select * from xx where user_id = #{userId} AND status = 1 order by latest_learn_time limit 1
//        LearningLesson lesson = lambdaQuery()
//                .eq(LearningLesson::getUserId, userId)
//                .eq(LearningLesson::getStatus, LessonStatus.LEARNING.getValue())
//                .orderByDesc(LearningLesson::getLatestLearnTime)
//                .last("limit 1")
//                .one();
//        if (lesson == null){
//            return null;
//        }
//        // 3.拷贝PO基础属性到VO
//        LearningLessonVO vo = BeanUtils.copyBean(lesson, LearningLessonVO.class);
//        // 4、查询课程信息
//        CourseFullInfoDTO cInfo = courseClient.getCourseInfoById(lesson.getCourseId(), false, false);
//        if (cInfo == null) {
//            throw new BadRequestException("课程不存在");
//        }
//        vo.setCourseName(cInfo.getName());
//        vo.setCourseCoverUrl(cInfo.getCoverUrl());
//        vo.setSections(cInfo.getSectionNum());
//        // 5.统计课表中的课程数量 select count(1) from xxx where user_id = #{userId}
//        Integer courseAmount = lambdaQuery()
//                .eq(LearningLesson::getUserId, userId)
//                .count();
//        vo.setCourseAmount(courseAmount);
//        // 6、查询小节信息
//        List<CataSimpleInfoDTO> cataInfos =  catalogueClient.batchQueryCatalogue(CollUtils.singletonList(lesson.getLatestSectionId()));
//        if (!CollUtils.isEmpty(cataInfos)) {
//            CataSimpleInfoDTO cataInfo = cataInfos.get(0);
//            vo.setLatestSectionName(cataInfo.getName());
//            vo.setLatestSectionIndex(cataInfo.getCIndex());
//        }
//
//        return vo;
//    }
//
//    @Override
//    public void deleteCourseFromLesson(Long userId, Long courseId) {
//        // 1.获取当前登录用户
//        if (userId == null) {
//            userId = UserContext.getUser();
//        }
//        // 2.删除课程
//        remove(buildUserIdAndCourseIdWrapper(userId, courseId));
//    }
//
//    @Override
//    public Long isLessonValid(Long courseId) {
//        // 1.获取登录用户
//        Long userId = UserContext.getUser();
//        if (userId == null) {
//            return null;
//        }
//        // 2.查询课程
//        LearningLesson lesson = getOne(buildUserIdAndCourseIdWrapper(userId, courseId));
//        if (lesson == null) {
//            return null;
//        }
//        return lesson.getId();
//    }
//
//    @Override
//    public LearningLessonVO queryLessonByCourseId(Long courseId) {
//        Long userId = UserContext.getUser();
//        LearningLesson lesson = getOne(buildUserIdAndCourseIdWrapper(userId, courseId));
//        if (lesson != null){
//            return BeanUtils.copyBean(lesson, LearningLessonVO.class);
//        }
//        return null;
//    }
//
//    @Override
//    public Integer countLearningLessonByCourse(Long courseId) {
//        // select count(1) from xx where course_id = #{cc} AND status in (0, 1, 2)
//        return lambdaQuery()
//                .eq(LearningLesson::getCourseId, courseId)
//                .in(LearningLesson::getStatus,
//                        LessonStatus.NOT_BEGIN.getValue(),
//                        LessonStatus.LEARNING.getValue(),
//                        LessonStatus.FINISHED.getValue())
//                .count();
//    }
//
//    @Override
//    public LearningLesson queryByUserAndCourseId(Long userId, Long courseId) {
//        return getOne(buildUserIdAndCourseIdWrapper(userId, courseId));
//    }
//
//    @Override
//    public void createLearningPlan(Long courseId, Integer freq) {
//        // 1、获取当前登录的用户
//        Long userId = UserContext.getUser();
//        // 2、 查询课表中的指定课程有关的数据
//        LearningLesson lesson = queryByUserAndCourseId(userId, courseId);
//        AssertUtils.isNotNull(lesson, "课程信息不存在！");
//        // 3.修改数据
//        LearningLesson l = new LearningLesson();
//        l.setId(lesson.getId());
//        l.setWeekFreq(freq);
//        if(lesson.getPlanStatus() == PlanStatus.NO_PLAN) {
//            l.setPlanStatus(PlanStatus.PLAN_RUNNING);
//        }
//        updateById(l);
//    }
//
//    @Override
//    public LearningPlanPageVO queryMyPlans(PageQuery query) {
//        LearningPlanPageVO result = new LearningPlanPageVO();
//        // 1.获取当前登录用户
//        Long userId = UserContext.getUser();
//        // 2.获取本周起始时间
//        LocalDate now = LocalDate.now();
//        LocalDateTime begin = DateUtils.getWeekBeginTime(now);
//        LocalDateTime end = DateUtils.getWeekEndTime(now);
//        // 3.查询本周计划学习的所有课程，满足三个条件：属于当前用户、有学习计划、学习中
//        List<LearningLesson> lessons = lambdaQuery()
//                .eq(LearningLesson::getUserId, userId)
//                .eq(LearningLesson::getPlanStatus, PlanStatus.PLAN_RUNNING)
//                .in(LearningLesson::getStatus, LessonStatus.NOT_BEGIN, LessonStatus.LEARNING)
//                .list();
//        if (CollUtils.isEmpty(lessons)) {
//            return null;
//        }
//        // 4.统计当前用户每个课程的已学习小节数量
//        List<LearningRecord> learnedRecords = recordMapper.selectList(new QueryWrapper<LearningRecord>().lambda()
//                .eq(LearningRecord::getUserId, userId)
//                .eq(LearningRecord::getFinished, true)
//                .gt(LearningRecord::getFinishTime, begin)
//                .lt(LearningRecord::getFinishTime, end)
//        );
//        Map<Long, Long> countMap = learnedRecords.stream()
//                .collect(Collectors.groupingBy(LearningRecord::getLessonId, Collectors.counting()));
//
//        // 5.查询总的统计数据
//        // 5.1.本周总的已学习小节数量
//        int weekFinished = learnedRecords.size();
//        result.setWeekFinished(weekFinished);
//        // 5.2.本周总的计划学习小节数量
//        int weekTotalPlan = lessons.stream().mapToInt(LearningLesson::getWeekFreq).sum();
//        result.setWeekTotalPlan(weekTotalPlan);
//        // 5.3.本周学习积分
//        result.setWeekPoints(weekFinished * 25); // 积分规则：每学习一个小节，获得25积分
//
//        // 6.处理分页数据
//        // 6.1.分页查询课表信息以及学习计划信息
//        Page<LearningLesson> p = new Page<>(query.getPageNo(), query.getPageSize(), lessons.size());
//        List<LearningLesson> records = CollUtils.sub(lessons, query.from(), query.from() + query.getPageSize());
//        if (CollUtils.isEmpty(records)) {
//            return result;
//        }
//        // 6.2.查询课表对应的课程信息
//        Map<Long, CourseSimpleInfoDTO> cMap = queryCourseSimpleInfoList(records);
//        // 6.3.组装数据VO
//        List<LearningPlanVO> voList = new ArrayList<>(records.size());
//        for (LearningLesson r : records) {
//            // 6.4.1.拷贝基础属性到vo
//            LearningPlanVO vo = BeanUtils.copyBean(r, LearningPlanVO.class);
//            // 6.4.2.填充课程详细信息
//            CourseSimpleInfoDTO cInfo = cMap.get(r.getCourseId());
//            if (cInfo != null) {
//                vo.setCourseName(cInfo.getName());
//                vo.setSections(cInfo.getSectionNum());
//            }
//            // 6.4.3.每个课程的本周已学习小节数量
//            vo.setWeekLearnedSections(countMap.getOrDefault(r.getId(), 0L).intValue());
//            voList.add(vo);
//        }
//        return result.pageInfo(p.getTotal(), p.getPages(), voList);
//    }
//    // 实现定期根据expireTime过期时间与现在时间对比，如果课程过期了，则修改状态为过期
//    @Override
//    @Scheduled(fixedDelay = 1000 * 10) // 每天凌晨执行一次
//    public void isOverdueLearningStatus() {
//        log.info("开始检查课程是否过期...");
//
//        // 1. 获取当前时间
//        LocalDateTime now = LocalDateTime.now();
//
//        // 2. 查询所有未过期且状态不是已过期的课程
//        List<LearningLesson> lessons = lambdaQuery()
//                .lt(LearningLesson::getExpireTime, now) // 过期时间小于当前时间
//                .ne(LearningLesson::getStatus, LessonStatus.EXPIRED.getValue()) // 状态不是已过期
//                .list();
//
//        if (CollUtils.isEmpty(lessons)) {
//            log.info("没有需要更新的过期课程");
//            return;
//        }
//
//        // 3. 更新课程状态为已过期
//        List<LearningLesson> updatedLessons = lessons.stream()
//                .map(lesson -> {
//                    lesson.setStatus(LessonStatus.of(LessonStatus.EXPIRED.getValue()));
//                    return lesson;
//                })
//                .collect(Collectors.toList());
//
//        // 4. 批量更新
//        updateBatchById(updatedLessons);
//
//        log.info("已更新 {} 门课程状态为已过期", updatedLessons.size());
//    }
//
//
//    private Map<Long, CourseSimpleInfoDTO> queryCourseSimpleInfoList(List<LearningLesson> records) {
//        // 3.1.获取课程id
//        Set<Long> cIds = records.stream().map(LearningLesson::getCourseId).collect(Collectors.toSet());
//        // 3.2.查询课程信息
//        List<CourseSimpleInfoDTO> cInfoList = courseClient.getSimpleInfoList(cIds);
//        if (CollUtils.isEmpty(cInfoList)) {
//            // 课程不存在，无法添加
//            throw new BadRequestException("课程信息不存在！");
//        }
//        // 3.3.把课程集合处理成Map，key是courseId，值是course本身
//        Map<Long, CourseSimpleInfoDTO> cMap = cInfoList.stream()
//                .collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));
//        return cMap;
//    }
//
//    private LambdaQueryWrapper<LearningLesson> buildUserIdAndCourseIdWrapper(Long userId, Long courseId) {
//        LambdaQueryWrapper<LearningLesson> queryWrapper = new QueryWrapper<LearningLesson>()
//                .lambda()
//                .eq(LearningLesson::getUserId, userId)
//                .eq(LearningLesson::getCourseId, courseId);
//        return queryWrapper;
//    }

    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final LearningRecordMapper recordMapper;

    @Override
    @Transactional
    public void addUserLessons(Long userId, List<Long> courseIds) {
        // 1.查询课程有效期
        List<CourseSimpleInfoDTO> cInfoList = courseClient.getSimpleInfoList(courseIds);
        if (CollUtils.isEmpty(cInfoList)) {
            // 课程不存在，无法添加
            log.error("课程信息不存在，无法添加到课表");
            return;
        }
        // 2.循环遍历，处理LearningLesson数据
        List<LearningLesson> list = new ArrayList<>(cInfoList.size());
        for (CourseSimpleInfoDTO cInfo : cInfoList) {
            LearningLesson lesson = new LearningLesson();
            // 2.1.获取过期时间
            Integer validDuration = cInfo.getValidDuration();
            if (validDuration != null && validDuration > 0) {
                LocalDateTime now = LocalDateTime.now();
                lesson.setCreateTime(now);
                lesson.setExpireTime(now.plusMonths(validDuration));
            }
            // 2.2.填充userId和courseId
            lesson.setUserId(userId);
            lesson.setCourseId(cInfo.getId());
            list.add(lesson);
        }
        // 3.批量新增
        saveBatch(list);
    }

    @Override
    public PageDTO<LearningLessonVO> queryMyLessons(PageQuery query) {
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        // 2.分页查询
        // select * from learning_lesson where user_id = #{userId} order by latest_learn_time limit 0, 5
        Page<LearningLesson> page = lambdaQuery()
                .eq(LearningLesson::getUserId, userId) // where user_id = #{userId}
                .page(query.toMpPage("latest_learn_time", false));
        List<LearningLesson> records = page.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }
        // 3.查询课程信息
        Map<Long, CourseSimpleInfoDTO> cMap = queryCourseSimpleInfoList(records);

        // 4.封装VO返回
        List<LearningLessonVO> list = new ArrayList<>(records.size());
        // 4.1.循环遍历，把LearningLesson转为VO
        for (LearningLesson r : records) {
            // 4.2.拷贝基础属性到vo
            LearningLessonVO vo = BeanUtils.copyBean(r, LearningLessonVO.class);
            // 4.3.获取课程信息，填充到vo
            CourseSimpleInfoDTO cInfo = cMap.get(r.getCourseId());
            vo.setCourseName(cInfo.getName());
            vo.setCourseCoverUrl(cInfo.getCoverUrl());
            vo.setSections(cInfo.getSectionNum());
            list.add(vo);
        }
        return PageDTO.of(page, list);
    }

    private Map<Long, CourseSimpleInfoDTO> queryCourseSimpleInfoList(List<LearningLesson> records) {
        // 3.1.获取课程id
        Set<Long> cIds = records.stream().map(LearningLesson::getCourseId).collect(Collectors.toSet());
        // 3.2.查询课程信息
        List<CourseSimpleInfoDTO> cInfoList = courseClient.getSimpleInfoList(cIds);
        if (CollUtils.isEmpty(cInfoList)) {
            // 课程不存在，无法添加
            throw new BadRequestException("课程信息不存在！");
        }
        // 3.3.把课程集合处理成Map，key是courseId，值是course本身
        Map<Long, CourseSimpleInfoDTO> cMap = cInfoList.stream()
                .collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));
        return cMap;
    }

    @Override
    public LearningLessonVO queryMyCurrentLesson() {
        // 1.获取当前登录的用户
        Long userId = UserContext.getUser();
        // 2.查询正在学习的课程 select * from xx where user_id = #{userId} AND status = 1 order by latest_learn_time limit 1
        LearningLesson lesson = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getStatus, LessonStatus.LEARNING.getValue())
                .orderByDesc(LearningLesson::getLatestLearnTime)
                .last("limit 1")
                .one();
        if (lesson == null) {
            return null;
        }
        // 3.拷贝PO基础属性到VO
        LearningLessonVO vo = BeanUtils.copyBean(lesson, LearningLessonVO.class);
        // 4.查询课程信息
        CourseFullInfoDTO cInfo = courseClient.getCourseInfoById(lesson.getCourseId(), false, false);
        if (cInfo == null) {
            throw new BadRequestException("课程不存在");
        }
        vo.setCourseName(cInfo.getName());
        vo.setCourseCoverUrl(cInfo.getCoverUrl());
        vo.setSections(cInfo.getSectionNum());
        // 5.统计课表中的课程数量 select count(1) from xxx where user_id = #{userId}
        Integer courseAmount = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .count();
        vo.setCourseAmount(courseAmount);
        // 6.查询小节信息
        List<CataSimpleInfoDTO> cataInfos =
                catalogueClient.batchQueryCatalogue(CollUtils.singletonList(lesson.getLatestSectionId()));
        if (!CollUtils.isEmpty(cataInfos)) {
            CataSimpleInfoDTO cataInfo = cataInfos.get(0);
            vo.setLatestSectionName(cataInfo.getName());
            vo.setLatestSectionIndex(cataInfo.getCIndex());
        }
        return vo;
    }

    @Override
    public LearningLessonVO queryLessonByCourseId(Long courseId) {
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        // 2.查询课程信息 select * from xx where user_id = #{userId} AND course_id = #{courseId}
        LearningLesson lesson = getOne(buildUserIdAndCourseIdWrapper(userId, courseId));
        if (lesson == null) {
            return null;
        }
        // 3.处理VO
        return BeanUtils.copyBean(lesson, LearningLessonVO.class);
    }

    @Override
    public void deleteCourseFromLesson(Long userId, Long courseId) {
        // 1.获取当前登录用户
        if (userId == null) {
            userId = UserContext.getUser();
        }
        // 2.删除课程
        remove(buildUserIdAndCourseIdWrapper(userId, courseId));
    }

    @Override
    public Integer countLearningLessonByCourse(Long courseId) {
        // select count(1) from xx where course_id = #{cc} AND status in (0, 1, 2)
        return lambdaQuery()
                .eq(LearningLesson::getCourseId, courseId)
                .in(LearningLesson::getStatus,
                        LessonStatus.NOT_BEGIN.getValue(),
                        LessonStatus.LEARNING.getValue(),
                        LessonStatus.FINISHED.getValue())
                .count();
    }

    @Override
    public Long isLessonValid(Long courseId) {
        // 1.获取登录用户
        Long userId = UserContext.getUser();
        if (userId == null) {
            return null;
        }
        // 2.查询课程
        LearningLesson lesson = getOne(buildUserIdAndCourseIdWrapper(userId, courseId));
        if (lesson == null) {
            return null;
        }
        return lesson.getId();
    }

    @Override
    public LearningLesson queryByUserAndCourseId(Long userId, Long courseId) {
        return getOne(buildUserIdAndCourseIdWrapper(userId, courseId));
    }

    @Override
    public void createLearningPlan(Long courseId, Integer freq) {
        // 1.获取当前登录的用户
        Long userId = UserContext.getUser();
        // 2.查询课表中的指定课程有关的数据
        LearningLesson lesson = queryByUserAndCourseId(userId, courseId);
        AssertUtils.isNotNull(lesson, "课程信息不存在！");
        // 3.修改数据
        LearningLesson l = new LearningLesson();
        l.setId(lesson.getId());
        l.setWeekFreq(freq);
        if(lesson.getPlanStatus() == PlanStatus.NO_PLAN) {
            l.setPlanStatus(PlanStatus.PLAN_RUNNING);
        }
        updateById(l);
    }

    @Override
    public LearningPlanPageVO queryMyPlans(PageQuery query) {
        LearningPlanPageVO result = new LearningPlanPageVO();
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        // 2.获取本周起始时间
        LocalDate now = LocalDate.now();
        LocalDateTime begin = DateUtils.getWeekBeginTime(now);
        LocalDateTime end = DateUtils.getWeekEndTime(now);
        // 3.查询总的统计数据
        // 3.1.本周总的已学习小节数量
        Integer weekFinished = recordMapper.selectCount(new LambdaQueryWrapper<LearningRecord>()
                .eq(LearningRecord::getUserId, userId)
                .eq(LearningRecord::getFinished, true)
                .gt(LearningRecord::getFinishTime, begin)
                .lt(LearningRecord::getFinishTime, end)
        );
        result.setWeekFinished(weekFinished);
        // 3.2.本周总的计划学习小节数量
        Integer weekTotalPlan = getBaseMapper().queryTotalPlan(userId);
        result.setWeekTotalPlan(weekTotalPlan);
        // 3.3.本周学习积分
        result.setWeekPoints(weekFinished * 25); // 积分规则：每学习一个小节，获得25积分

        // 4.查询分页数据
        // 4.1.分页查询课表信息以及学习计划信息
        Page<LearningLesson> p = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getPlanStatus, PlanStatus.PLAN_RUNNING)
                .in(LearningLesson::getStatus, LessonStatus.NOT_BEGIN, LessonStatus.LEARNING)
                .page(query.toMpPage("latest_learn_time", false));
        List<LearningLesson> records = p.getRecords();
        if (CollUtils.isEmpty(records)) {
            return result.emptyPage(p);
        }
        // 4.2.查询课表对应的课程信息
        Map<Long, CourseSimpleInfoDTO> cMap = queryCourseSimpleInfoList(records);
        // 4.3.统计每一个课程本周已学习小节数量
        List<IdAndNumDTO> list = recordMapper.countLearnedSections(userId, begin, end);
        Map<Long, Integer> countMap = IdAndNumDTO.toMap(list);
        // 4.4.组装数据VO
        List<LearningPlanVO> voList = new ArrayList<>(records.size());
        for (LearningLesson r : records) {
            // 4.4.1.拷贝基础属性到vo
            LearningPlanVO vo = BeanUtils.copyBean(r, LearningPlanVO.class);
            // 4.4.2.填充课程详细信息
            CourseSimpleInfoDTO cInfo = cMap.get(r.getCourseId());
            if (cInfo != null) {
                vo.setCourseName(cInfo.getName());
                vo.setSections(cInfo.getSectionNum());
            }
            // 4.4.3.每个课程的本周已学习小节数量
            vo.setWeekLearnedSections(countMap.getOrDefault(r.getId(), 0));
            voList.add(vo);
        }
        return result.pageInfo(p.getTotal(), p.getPages(), voList);
    }

    @Override
    @Scheduled(fixedDelay = 1000 * 10) // 每天凌晨执行一次
    public void isOverdueLearningStatus() {
        log.info("开始检查课程是否过期...");

        // 1. 获取当前时间
        LocalDateTime now = LocalDateTime.now();

        // 2. 查询所有未过期且状态不是已过期的课程
        List<LearningLesson> lessons = lambdaQuery()
                .lt(LearningLesson::getExpireTime, now) // 过期时间小于当前时间
                .ne(LearningLesson::getStatus, LessonStatus.EXPIRED.getValue()) // 状态不是已过期
                .list();

        if (CollUtils.isEmpty(lessons)) {
            log.info("没有需要更新的过期课程");
            return;
        }

        // 3. 更新课程状态为已过期
        List<LearningLesson> updatedLessons = lessons.stream()
                .map(lesson -> {
                    lesson.setStatus(LessonStatus.of(LessonStatus.EXPIRED.getValue()));
                    return lesson;
                })
                .collect(Collectors.toList());

        // 4. 批量更新
        updateBatchById(updatedLessons);

        log.info("已更新 {} 门课程状态为已过期", updatedLessons.size());
    }

    private LambdaQueryWrapper<LearningLesson> buildUserIdAndCourseIdWrapper(Long userId, Long courseId) {
        LambdaQueryWrapper<LearningLesson> queryWrapper = new QueryWrapper<LearningLesson>()
                .lambda()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getCourseId, courseId);
        return queryWrapper;
    }
}
